#ifndef _DRAYDROP_H
#define _DRAYDROP_H
//////////////////////////////////////////////////////////
class CDataObject : public IDataObject
{
public:
	// IUnknown members
	HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
	ULONG   __stdcall AddRef (void);
	ULONG   __stdcall Release (void);

	// IDataObject members
	HRESULT __stdcall GetData (FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
	HRESULT __stdcall GetDataHere (FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
	HRESULT __stdcall QueryGetData (FORMATETC *pFormatEtc);
	HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut);
	HRESULT __stdcall SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease);
	HRESULT __stdcall EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
	HRESULT __stdcall DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *, DWORD *);
	HRESULT __stdcall DUnadvise (DWORD      dwConnection);
	HRESULT __stdcall EnumDAdvise (IEnumSTATDATA **ppEnumAdvise);
		// Constructor / Destructor
	CDataObject ();
	~CDataObject ();
	void AddFromatEtc(FORMATETC *fmtetc, STGMEDIUM *stgmeds);
private:
	CStdPtrArray m_pFormatEtc;
	CStdPtrArray m_pStgMedium;
	LONG m_lRefCount;
	int LookupFormatEtc(FORMATETC *pFormatEtc);
	HGLOBAL DupGlobalMemMem (HGLOBAL hMem);
};
/////////////////////////////////////////////////////////////////

class CEnumFormatEtc : public IEnumFORMATETC 
{ 
public: 
	// 
	// IUnknown members 
	// 
	HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject); 
	ULONG __stdcall AddRef (void); 
	ULONG __stdcall Release (void); 
	// 
	// IEnumFormatEtc members 
	// 
	HRESULT __stdcall Next (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched); 
	HRESULT __stdcall Skip (ULONG celt);  
	HRESULT __stdcall Reset (void); 
	HRESULT __stdcall Clone (IEnumFORMATETC ** ppEnumFormatEtc); 

	// 
	// Construction / Destruction 
	// 
	CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats); 
	~CEnumFormatEtc(); 
	static HRESULT CEnumFormatEtc::CreateEnumFormatEtc (UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc);

private: 

	void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source);
	LONG m_lRefCount; // Reference count for this COM interface 
	ULONG m_nIndex; // current enumerator index 
	ULONG m_nNumFormats; // number of FORMATETC members 
	FORMATETC * m_pFormatEtc; // array of FORMATETC objects 
}; 

////////////////////////////////////////////////////////////////////////////////

class CDropSource : public IDropSource 
{ 
public: 
	HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject); 
	ULONG __stdcall AddRef (void); 
	ULONG __stdcall Release (void); 
	// 
	// IDropSource members 
	// 
	HRESULT __stdcall QueryContinueDrag (BOOL fEscapePressed, DWORD grfKeyState); 
	HRESULT __stdcall GiveFeedback (DWORD dwEffect); 
	// 
	// Constructor / Destructor 
	// 
	CDropSource(); 
	~CDropSource(); 
	static HRESULT CreateDropSource (IDropSource **ppDropSource);
private: 
	LONG  m_lRefCount; 
}; 

//////////////////////////////////////////////////////////////
class CDropTarget : public IDropTarget
{
public:
	CDropTarget();
	~CDropTarget();

	bool DragDropRegister(CWindowUI* pWindow, DWORD dwAcceptKeyState = MK_LBUTTON);
public:
	// Interface IDropTarget
	HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
	HRESULT STDMETHODCALLTYPE DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
	HRESULT STDMETHODCALLTYPE DragLeave(void);
	HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect);

	// Interface IUnknown	
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);
	ULONG STDMETHODCALLTYPE AddRef(void);
	ULONG STDMETHODCALLTYPE Release(void);

protected:
	ULONG cRefs;
	CWindowUI* m_pWindow;
	DWORD m_AcceptKeyState;
};
#endif